﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;


namespace ZhimeiSoft.Framework.Common.RefectUtils
{
    public class ReflectHelper
    {
        private static ReflectHelper instance;
        private static Dictionary<string, Assembly> assemblyPool = new Dictionary<string, Assembly>();

        public static ReflectHelper Instance
        {
            get
            {
                if (instance == null)
                    instance = new ReflectHelper();
                return instance;
            }
        }

        private ReflectHelper()
        {
        }

        public static string GetUriPath(string uriString)
        {
            Uri uri = new Uri(uriString);
            string text = uriString.Remove(uriString.Length - uri.Segments[uri.Segments.Length - 1].Length);
            if (!text.EndsWith("/"))
            {
                text += "/";
            }

            if (text.StartsWith("file:///"))
            {
                text = text.Substring(8);
            }

            return text;
        }

        public Assembly GetAssembly(Assembly sender, string assemblyName)
        {
            if (ReflectHelper.assemblyPool.ContainsKey(assemblyName))
            {
                return ReflectHelper.assemblyPool[assemblyName];
            }
            string assemblyFile = ReflectHelper.GetUriPath(sender.CodeBase) + assemblyName;
            Assembly assembly = Assembly.LoadFrom(assemblyFile);
            ReflectHelper.assemblyPool.Add(assemblyName, assembly);
            return assembly;
        }

        public object CreateObject(Assembly sender, string assemblyName, string typeFullName, params object[] args)
        {
            if (sender.GetName().Name == assemblyName)
            {
                if (!ReflectHelper.assemblyPool.ContainsKey(assemblyName))
                {
                    ReflectHelper.assemblyPool.Add(assemblyName, sender);
                }
                return this.CreateObject(sender, typeFullName, args);
            }
            return this.CreateObject(ReflectHelper.GetUriPath(sender.CodeBase), assemblyName, typeFullName, args);

        }

        public object CreateObject(string location, string assemblyName, string typeFullName, params object[] args)
        {
            if (ReflectHelper.assemblyPool.ContainsKey(assemblyName))
            {
                Assembly asm = ReflectHelper.assemblyPool[assemblyName];
                return this.CreateObject(asm, typeFullName, args);
            }
            string assemblyFile = location + assemblyName + ".dll";
            Assembly assembly = Assembly.LoadFrom(assemblyFile);
            ReflectHelper.assemblyPool.Add(assemblyName, assembly);
            return this.CreateObject(assembly, typeFullName, args);
        }

        public object InvokeMethod(object obj, string methodName, params object[] args)
        {
            if (obj == null)
            {
                throw new Exception("obj不能为空！");
            }
            MethodInfo method = obj.GetType().GetMethod(methodName);
            if (methodName == null)
            {
                throw new Exception("方法不存在！");
            }
            return method.Invoke(obj, args);
        }

        private object CreateObject(Assembly asm, string typeFullName, params object[] args)
        {
            object obj = asm.CreateInstance(typeFullName, true, BindingFlags.CreateInstance, null, args, null, null);
            if (obj == null)
            {
                throw new Exception(asm.GetName().EscapedCodeBase + "中不存在类" + typeFullName);
            }
            return obj;
        }

    }
}
